﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Data;
using System.Text;
using System.Windows.Forms;

namespace QuantumFractals
{
    public partial class FractalPanel : Panel
    {
        private Bitmap fractalBitmap = null;
        public Bitmap Bitmap
        {
            get 
            { 
                return fractalBitmap; 
            }
            set 
            {
                if (fractalBitmap != null)
                    fractalBitmap.Dispose();
                fractalBitmap = value;
                //bitmap.MakeTransparent(Color.Blue);
                zoomRectangles.Clear();
                if (fractalBitmap != null)
                {
                    zoomRectangles.Push(new Rectangle(0, 0, fractalBitmap.Width, fractalBitmap.Height));
                    Refresh();
                }
            }
        }
        public delegate void ZoomHandler(object sender, int zoom);
        public event ZoomHandler Zoom;

        private Stack<Rectangle> zoomRectangles = new Stack<Rectangle>();
        private Point lastMouse = new Point(0, 0);
        private Rectangle lastDrawed = new Rectangle(0, 0, 0, 0);

        public FractalPanel()
        {
            InitializeComponent();
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            if (zoomRectangles.Count > 0)
            {
                e.Graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
                e.Graphics.SmoothingMode = SmoothingMode.HighQuality;
                e.Graphics.CompositingQuality = CompositingQuality.HighQuality;
                e.Graphics.DrawImage(fractalBitmap,
                    new Rectangle(new Point(0, 0), Size),
                    zoomRectangles.Peek(),
                    GraphicsUnit.Pixel);
            }
            else
                e.Graphics.Clear(BackColor);
        }

        protected override void OnResize(EventArgs eventargs)
        {
            Refresh();
        }

        private void SetLastDrawed(Point newPoint)
        {
            lastDrawed.X = Math.Min(lastMouse.X, newPoint.X);
            lastDrawed.Y = Math.Min(lastMouse.Y, newPoint.Y);
            lastDrawed.Width = Math.Abs(lastMouse.X - newPoint.X);
            lastDrawed.Height = Math.Abs(lastMouse.Y - newPoint.Y);
        }

        protected override void OnMouseDown(MouseEventArgs e)
        {
            base.OnMouseDown(e);
            if (e.Button == MouseButtons.Left)
            {
                lastMouse = e.Location;
                SetLastDrawed(e.Location);
                Graphics graphics = CreateGraphics();
                graphics.DrawRectangle(new Pen(Color.Blue), lastDrawed);
            }
        }

        protected override void OnMouseMove(MouseEventArgs e)
        {
            base.OnMouseMove(e);
            if (e.Button == MouseButtons.Left)
            {
                Refresh();
                SetLastDrawed(e.Location);
                Graphics graphics = CreateGraphics();
                graphics.DrawRectangle(new Pen(Color.Blue), lastDrawed);
            }
        }

        protected override void OnMouseUp(MouseEventArgs e)
        {
            base.OnMouseUp(e);
            switch (e.Button)
            {
                case MouseButtons.Left:
                    if (Math.Max(lastDrawed.Width, lastDrawed.Height) < 10)
                    {
                        int x = e.X * zoomRectangles.Peek().Width / Width + zoomRectangles.Peek().X;
                        int y = e.Y * zoomRectangles.Peek().Height / Height + zoomRectangles.Peek().Y;
                        int w = zoomRectangles.Peek().Width / 4;
                        zoomRectangles.Push(new Rectangle(x - w, y - w, w * 2, w * 2));
                    }
                    else
                    {
                        int x = Math.Min(e.X, lastDrawed.X) * zoomRectangles.Peek().Width / Width + 
                            zoomRectangles.Peek().X;
                        int y = Math.Min(e.Y, lastDrawed.Y) * zoomRectangles.Peek().Height / Height + 
                            zoomRectangles.Peek().Y;
                        int w = Math.Max(lastDrawed.Width, lastDrawed.Height) * zoomRectangles.Peek().Width / 
                            Width;
                        zoomRectangles.Push(new Rectangle(x, y, w, w));
                    }
                    break;
                case MouseButtons.Right:
                    if (zoomRectangles.Count > 1)
                        zoomRectangles.Pop();
                    break;
            }
            lastMouse.X = 0;
            lastMouse.Y = 0;
            if (Zoom != null)
                Zoom(this, fractalBitmap.Width * 100 / zoomRectangles.Peek().Width);
            Refresh();
        }
    }
}
